package com.canyou.system;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.canyou.api.BaseApiController;
import com.canyou.api.ResponseBO;
import com.canyou.constants.CommonConstants;
import com.canyou.constants.MsgConstants;
import com.canyou.common.DataImportVO;
import com.canyou.system.importhandler.UserImportHandler;
import com.canyou.system.entity.user.UserDTO;
import com.canyou.system.entity.user.UserDetailVO;
import com.canyou.system.entity.user.UserListVO;
import com.canyou.system.entity.user.UserPasswordUpdateDTO;
import com.canyou.system.model.Menu;
import com.canyou.system.model.User;
import com.canyou.system.service.MenuService;
import com.canyou.system.service.UserService;
import com.canyou.utils.DownloadUtils;
import com.canyou.utils.ExcelUtils;
import com.canyou.utils.PathUtils;
import com.canyou.utils.StringUtils;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import static com.canyou.api.ResponseBO.*;

/**
 * 用户管理
 *
 * @author canyou
 * @since 2019-05-14
 */
@Api(tags = "用户管理")
@ApiSort(1001)
@RestController
@RequestMapping("/user")
@Validated
public class UserController extends BaseApiController {

    @Autowired
    private UserService userService;

    @Autowired
    private MenuService menuService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @ApiOperation(value = "获取当前授权用户信息")
    @GetMapping("/current")
    public ResponseBO<UserDetailVO> getCurrent() {
        UserDetailVO user = userService.getUserDetailById(userService.getCurrentUserId());
        List<Menu> menList = menuService.getMenuListByUserId(user.getId());
        user.setOwnerMenuList(menList);
        return ok(user);
    }

    @ApiOperation(value = "获取用户分页")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNumber", paramType = "query", value = "当前第几页", dataType = "int", example = "1"),
            @ApiImplicitParam(name = "pageSize", paramType = "query", value = "每页记录数", dataType = "int", example = "10"),
            @ApiImplicitParam(name = "username", paramType = "query", value = "账号", dataType = "string"),
            @ApiImplicitParam(name = "realName", paramType = "query", value = "姓名", dataType = "string")
    })
    @PreAuthorize("hasPerm('user')")
    @GetMapping("/get_page")
    public ResponseBO<IPage<UserListVO>> getPageList(@RequestParam(defaultValue = PAGE_INDEX, required = false) int pageNumber,
                                                     @RequestParam(defaultValue = PAGE_SIZE, required = false) int pageSize,
                                                     @RequestParam(required = false) String username,
                                                     @RequestParam(required = false) String realName) {
        IPage<UserListVO> page = new Page<>(pageNumber, pageSize);
        IPage<UserListVO> user = userService.getPageList(page, username, realName);
        return ok(user);
    }

    @ApiOperation(value = "获取用户详情")
    @ApiImplicitParam(name = "id", paramType = "query", value = "用户id", dataType = "Long", required = true, example = "1")
    @PreAuthorize("hasPerm('user')")
    @GetMapping("/get_info")
    public ResponseBO<UserDetailVO> getUser(@NotNull(message = "用户id不能为空")
                                            @RequestParam(required = false) Long id) {
        UserDetailVO user = userService.getUserDetailById(id);
        user.setRoleId(userService.getRoleIdListByUserId(id));
        return ok(user);
    }

    @ApiOperation(value = "新增编辑用户")
    @PreAuthorize("hasPerm('user:add','user:edit')")
    @PostMapping("/save")
    public ResponseBO saveUser(@ApiParam(name = "userDTO", type = "UserDTO", value = "用户新增编辑数据", required = true)
                               @Valid
                               @NotNull(message = "用户信息不能为空")
                               @RequestBody UserDTO userDTO) {
        Long userId = userDTO.getId();
        if (userService.existUser(userDTO.getUsername(), userId)) {
            return illegal("用户名已存在");
        }
        return result(userService.saveOrUpdateUser(userDTO), userId);
    }

    @ApiOperation(value = "删除用户")
    @PreAuthorize("hasPerm('user:del')")
    @PostMapping("/remove")
    public ResponseBO removeUser(@ApiParam(name = "id", type = "Long", value = "用户id", required = true, example = "1")
                                 @Valid
                                 @NotNull(message = "用户id不能为空")
                                 @RequestBody Long id) {
        return ok(userService.removeUserById(id), MsgConstants.DEL_SUCCESS);
    }

    @ApiOperation(value = "修改密码")
    @PostMapping(value = "/edit_password")
    public ResponseBO editPassword(@ApiParam(name = "userPasswordUpdateDTO", type = "UserPasswordUpdateDTO", value = "用户修改密码数据", required = true)
                                   @Valid
                                   @NotNull(message = "用户修改密码信息不能为空")
                                   @RequestBody UserPasswordUpdateDTO userPasswordUpdateDTO) {
        User user = userService.getById(userService.getCurrentUserId());
        if (!passwordEncoder.matches(userPasswordUpdateDTO.getPassword(), user.getPassword())) {
            return illegal("旧密码不正确");
        }
        user.setPassword(passwordEncoder.encode(userPasswordUpdateDTO.getNewPassword()));
        boolean res = userService.updateById(user);
        return ok(res, "修改密码成功");
    }

    @ApiOperation(value = "重置密码")
    @PreAuthorize("hasPerm('user:resetPass')")
    @PostMapping(value = "/reset_password")
    public ResponseBO resetPassword(@ApiParam(name = "userId", type = "Long", value = "用户id", required = true, example = "1")
                                    @Valid
                                    @NotNull(message = "用户id不能为空")
                                    @RequestBody Long userId) {
        User user = userService.getById(userId);
        if (user == null) {
            return illegal(StringUtils.format("userId: {} 对应的用户不存在", userId));
        }
        user.setPassword(passwordEncoder.encode(CommonConstants.DEFAULT_PASSWORD));
        boolean res = userService.updateById(user);
        return ok(res, "重置密码成功");
    }

    @ApiOperation(value = "用户Excel导出")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", paramType = "query", value = "账号", dataType = "string"),
            @ApiImplicitParam(name = "realName", paramType = "query", value = "姓名", dataType = "string")
    })
    @PreAuthorize("hasPerm('user:export')")
    @GetMapping(value = "/export_excel")
    public void exportExcel(@RequestParam(required = false) String username,
                            @RequestParam(required = false) String realName) {
        List<UserListVO> list = userService.getList(username, realName);
        ExcelUtils.exportExcel(list, "用户信息", "用户列表", UserListVO.class, "用户列表.xlsx", response);
    }

    @ApiOperation(value = "用户导入模板下载")
    @PreAuthorize("hasPerm('user:import')")
    @GetMapping(value = "/download_template")
    public void downloadTemplate() throws IOException {
        File file = PathUtils.getClassPathResourceFile("template/import/user-template.xlsx");
        String fileName = "用户导入模板.xlsx";
        DownloadUtils.downFile(file, fileName, "application/vnd.ms-excel", response);
    }

    @ApiOperation(value = "用户Excel导入")
    @ApiImplicitParam(name = "file", value = "待上传的用户excel文件", paramType = "form",
            dataType = "MultipartFile", required = true)
    @PreAuthorize("hasPerm('user:import')")
    @PostMapping(value = "/import_excel")
    public ResponseBO<DataImportVO> importExcel(@NotNull(message = "用户excel文件不能为空")
                                                @RequestParam(value = "file") MultipartFile file) throws Exception {
        ImportParams params = new ImportParams();
        params.setHeadRows(1);
        params.setDataHandler(new UserImportHandler());
        List<Map<String, Object>> list = ExcelImportUtil.importExcel(file.getInputStream(), Map.class, params);
        DataImportVO importMessage = userService.importData(list);
        return ok(importMessage);
    }

}
